﻿function AzureOnlineTableRequestBuilder(context) {

    var self = this;

    var dispatcher = $({});

    var expression = ko.observable(null);

    var target;
    
    var builderContext = {
        highlightedExpression: ko.observable(null)
    };

    function init(observableString) {
        target = observableString;
        var initialString = observableString();
        var parser = new AzureTableFilterExpressionParser();
        var raw = parser.parseQuery(initialString);
        raw = raw ? raw.expression : null;
        if (raw) {
            expression(wrap(self, raw));
        } else {
            expression(new AzureTableQueryCompareExpressionModel(self, builderContext));
        }
        unhighlightAll();
    }

    var queryString = ko.computed(function () {
        var expr = expression();
        if (expr) return expr.queryString();
        return '';
    });

    var queryHtmlString = ko.computed(function () {
        var expr = expression();
        if (expr) return expr.queryHtmlString();
        return '';
    });

    var canRemove = ko.computed(function () {
        return false;
    });

    function invert() {
    }

    function removeExpr() {
    }

    function replaceChild(oldExpression, newExpression) {
        expression(newExpression);
        newExpression.parent(self);
    }

    function wrap(parent, expr) {
        if (!expr) return null;
        var res;
        switch (expr.type) {
            case 'func':
                res = new AzureTableQueryFuncExpressionModel(parent, builderContext);
                res.funcName(expr.funcName);
                res.arg(wrap(res, expr.arg));
                return res;
            case 'compare':
                res = new AzureTableQueryCompareExpressionModel(parent, builderContext);
                res.left(expr.left);
                res.operator(expr.operator);
                res.right(expr.right);
                res.edmType(expr.edmType);
                return res;
            case 'combine':
                res = new AzureTableQueryCombineExpressionModel(parent, builderContext);
                res.subexpressions.push(wrap(res, expr.left));
                res.operator(expr.operator);
                res.subexpressions.push(wrap(res, expr.left));
                return res;
            default:
                return null;
        }
    }

    function unhighlightAll() {
        builderContext.highlightedExpression(null);
    }
    
    function apply() {
        dispatcher.trigger('success');
        target(expression().queryString());
    }

    function addOnSuccess(handler) {
        dispatcher.bind('success', handler);
    };

    self.init = init;
    self.apply = apply;
    self.expression = expression;
    self.canRemove = canRemove;
    self.invert = invert;
    self.removeExpr = removeExpr;
    self.replaceChild = replaceChild;
    self.queryString = queryString;
    self.queryHtmlString = queryHtmlString;
    self.unhighlightAll = unhighlightAll;
    self.addOnSuccess = addOnSuccess;
}
